package cn.ondraw.ragflow.service.impl;

import cn.hutool.json.JSONUtil;
import cn.ondraw.ragflow.pojo.request.*;
import cn.ondraw.ragflow.pojo.response.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import cn.ondraw.ragflow.pojo.request.*;
import cn.ondraw.ragflow.pojo.response.*;
import cn.ondraw.ragflow.pojo.request.*;
import cn.ondraw.ragflow.pojo.response.*;
import cn.ondraw.ragflow.service.SessionRagFlowService;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 聊天会话服务实现类
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SessionRagFlowServiceImpl implements SessionRagFlowService {
    private final PythonApiCaller pythonApiCaller;

    private final ExecutorService sseExecutor = Executors.newCachedThreadPool();

    /**
     * 创建聊天会话
     *
     * @param chatId  聊天 ID
     * @param request 创建会话请求对象
     * @return 创建会话响应对象
     */
    @Override
    public CreateSessionResponse createSession(String chatId, CreateSessionRequest request) {
        String url = "/api/v1/chats/" + chatId + "/sessions";
        ResponseEntity<?> response = pythonApiCaller.callPostApi(url, request);
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, CreateSessionResponse.class, true);
    }

    /**
     * 更新聊天会话
     *
     * @param chatId    聊天 ID
     * @param sessionId 会话 ID
     * @param request   更新会话请求对象
     * @return 更新会话响应对象
     */
    @Override
    public UpdateSessionResponse updateSession(String chatId, String sessionId, UpdateSessionRequest request) {
        String url = "/api/v1/chats/" + chatId + "/sessions/" + sessionId;
        ResponseEntity<?> response = pythonApiCaller.callPutApi(url, request);
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, UpdateSessionResponse.class, true);
    }

    /**
     * 列出聊天会话
     *
     * @param request 列出会话请求对象
     * @return 列出会话响应对象
     */
    @Override
    public ListSessionsResponse listSessions(ListSessionsRequest request) {
        StringBuilder urlBuilder = new StringBuilder("/api/v1/chats/" + request.getChat_id() + "/sessions?");
        try {
            if (request.getPage() != null) {
                urlBuilder.append("page=").append(request.getPage()).append("&");
            }
            if (request.getPage_size() != null) {
                urlBuilder.append("page_size=").append(request.getPage_size()).append("&");
            }
            if (request.getOrderby() != null) {
                urlBuilder.append("orderby=").append(request.getOrderby()).append("&");
            }
            if (request.getDesc() != null) {
                urlBuilder.append("desc=").append(request.getDesc()).append("&");
            }
            if (request.getName() != null) {
                urlBuilder.append("name=").append(URLEncoder.encode(request.getName(), StandardCharsets.UTF_8)).append("&");
            }
            if (request.getId() != null) {
                urlBuilder.append("id=").append(URLEncoder.encode(request.getId(), StandardCharsets.UTF_8)).append("&");
            }
            if (request.getUser_id() != null) {
                urlBuilder.append("user_id=").append(URLEncoder.encode(request.getUser_id(), StandardCharsets.UTF_8)).append("&");
            }
            if (request.getChat_id() != null) {
                urlBuilder.append("chat_id=").append(URLEncoder.encode(request.getChat_id(), StandardCharsets.UTF_8)).append("&");
            }
            if (urlBuilder.charAt(urlBuilder.length() - 1) == '&') {
                urlBuilder.deleteCharAt(urlBuilder.length() - 1);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        ResponseEntity<?> response = pythonApiCaller.callGetApi(urlBuilder.toString());
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, ListSessionsResponse.class, true);
    }

    /**
     * 删除聊天会话
     *
     * @param chatId  聊天 ID
     * @param request 删除会话请求对象
     * @return 删除会话响应对象
     */
    @Override
    public DeleteSessionsResponse deleteSessions(String chatId, DeleteSessionsRequest request) {
        String url = "/api/v1/chats/" + chatId + "/sessions";
        ResponseEntity<?> response = pythonApiCaller.callDeleteApi(url, request);
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, DeleteSessionsResponse.class, true);
    }

    /**
     * 与助手对话
     *
     * @param chatId  聊天 ID
     * @param request 对话请求对象
     * @return 对话响应对象
     */
    @Override
    public SseEmitter converseWithAssistant(String chatId, ConverseRequest request) {
        SseEmitter emitter = new SseEmitter(60 * 60 * 1000L);
        emitter.onTimeout(emitter::complete);
        emitter.onCompletion(() -> log.info("SSE连接已关闭"));
        sseExecutor.submit(() -> {
            try {
                HttpResponse response = pythonApiCaller.callPostSSEApiRaw("/api/v1/chats/" + chatId + "/completions", request);
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    emitter.send(line);
                }
            } catch (Exception e) {
                emitter.completeWithError(e);
            } finally {
                emitter.complete();
            }
        });
        return emitter;
    }

    /**
     * 创建代理会话
     *
     * @param agentId 代理 ID
     * @param request 创建代理会话请求对象
     * @return 创建代理会话响应对象
     */
    @Override
    public CreateAgentSessionResponse createAgentSession(String agentId, CreateAgentSessionRequest request) {
        StringBuilder urlBuilder = new StringBuilder("/api/v1/agents/" + agentId + "/sessions");
        if (request.getUser_id() != null) {
            urlBuilder.append("?user_id=").append(request.getUser_id());
        }
        String url = urlBuilder.toString();
        ResponseEntity<?> response = pythonApiCaller.callPostApi(url, request);
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, CreateAgentSessionResponse.class, true);
    }

    /**
     * 与代理对话
     *
     * @param agentId 代理 ID
     * @param request 与代理对话请求对象
     * @return 与代理对话响应对象
     */
    @Override
    public SseEmitter converseWithAgent(String agentId, ConverseWithAgentRequest request) {
        SseEmitter emitter = new SseEmitter(60 * 60 * 1000L);
        emitter.onTimeout(emitter::complete);
        emitter.onCompletion(() -> log.info("SSE连接已关闭"));
        sseExecutor.submit(() -> {
            try {
                HttpResponse response = pythonApiCaller.callPostSSEApiRaw( "/api/v1/agents/" + agentId + "/completions", request);
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    emitter.send(line);
                }
            } catch (Exception e) {
                emitter.completeWithError(e);
            } finally {
                emitter.complete();
            }
        });
        return emitter;
    }

    /**
     * 列出代理会话
     *
     * @param request 列出代理会话请求对象
     * @return 列出代理会话响应对象
     */
    @Override
    public ListAgentSessionsResponse listAgentSessions(ListAgentSessionsRequest request) {
        StringBuilder urlBuilder = new StringBuilder("/api/v1/agents/" + request.getAgent_id() + "/sessions?");
        try {
            if (request.getPage() != null) {
                urlBuilder.append("page=").append(request.getPage()).append("&");
            }
            if (request.getPage_size() != null) {
                urlBuilder.append("page_size=").append(request.getPage_size()).append("&");
            }
            if (request.getOrderby() != null) {
                urlBuilder.append("orderby=").append(request.getOrderby()).append("&");
            }
            if (request.getDesc() != null) {
                urlBuilder.append("desc=").append(request.getDesc()).append("&");
            }
            if (request.getId() != null) {
                urlBuilder.append("id=").append(request.getId()).append("&");
            }
            if (request.getUser_id() != null) {
                urlBuilder.append("user_id=").append(request.getUser_id()).append("&");
            }
            if (request.getDsl() != null) {
                urlBuilder.append("dsl=").append(request.getDsl()).append("&");
            }
            if (urlBuilder.charAt(urlBuilder.length() - 1) == '&') {
                urlBuilder.deleteCharAt(urlBuilder.length() - 1);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String url = urlBuilder.toString();
        ResponseEntity<?> response = pythonApiCaller.callGetApi(url);
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, ListAgentSessionsResponse.class, true);
    }

    /**
     * 删除代理会话
     *
     * @param agentId 代理 ID
     * @param request 删除代理会话请求对象
     * @return 删除代理会话响应对象
     */
    @Override
    public DeleteAgentSessionsResponse deleteAgentSessions(String agentId, DeleteAgentSessionsRequest request) {
        String url = "/api/v1/agents/" + agentId + "/sessions";
        ResponseEntity<?> response = pythonApiCaller.callDeleteApi(url, request);
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, DeleteAgentSessionsResponse.class, true);
    }

    /**
     * 生成相关问题
     *
     * @param request 生成相关问题请求对象
     * @return 生成相关问题响应对象
     */
    @Override
    public RelatedQuestionsResponse generateRelatedQuestions(RelatedQuestionsRequest request) {
        String url = "/v1/conversation/related_questions";
        ResponseEntity<?> response = pythonApiCaller.callPostApi(url, request);
        return JSONUtil.toBean(response.getBody() != null ? response.getBody().toString() : null, RelatedQuestionsResponse.class, true);
    }
}
